package com.weijian.service.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.weijian.common.enums.GlobalErrorCodeConstants;
import com.weijian.common.exception.ServiceException;
import com.weijian.common.pojo.CommonResult;
import com.weijian.constants.RedisConstants;
import com.weijian.dal.entity.SetMeal;
import com.weijian.mapper.SetMealMapper;
import com.weijian.service.CategoryService;
import com.weijian.service.SetMealService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
@Slf4j
@RequiredArgsConstructor
public class SetMealServiceImpl extends ServiceImpl<SetMealMapper, SetMeal> implements SetMealService {

    final StringRedisTemplate stringRedisTemplate;

    @Override
    public CommonResult<List<SetMeal>> querySetMealByIds(List<Long> ids) {
        List<SetMeal> cachedSetMeals = new ArrayList<>();
        List<Long> missingIds = new ArrayList<>();
        // 1. 先尝试从 Redis 获取商品，并识别缺失的商品 ID
        for (Long id : ids) {
            String setMealKey = RedisConstants.CACHE_SETMEAL_KEY + id;
            String setMealJson = stringRedisTemplate.opsForValue().get(setMealKey);
            if (setMealJson != null) {
                cachedSetMeals.add(JSONUtil.toBean(setMealJson, SetMeal.class));
            } else {
                missingIds.add(id);
            }
        }
        log.info("redis获取套餐数量：{}", cachedSetMeals.size());
        // 2. 如果 Redis 中已找到全部商品，则直接返回
        if (cachedSetMeals.size() == ids.size()) {
            return CommonResult.success(cachedSetMeals);
        }
        // 3. 查询数据库补全缺失商品
        List<SetMeal> dbsetMeals = listByIds(missingIds);
        if (dbsetMeals.isEmpty()) {
            return CommonResult.error(GlobalErrorCodeConstants.NOT_FOUND);
        }
        // 4. 将数据库查询结果写入 Redis 缓存
        dbsetMeals.forEach(setMeal -> {
            String setMealKey = RedisConstants.CACHE_SETMEAL_KEY + setMeal.getId();
            stringRedisTemplate.opsForValue().set(setMealKey, JSONUtil.toJsonStr(setMeal));
        });
        // 5. 合并缓存和数据库数据
        cachedSetMeals.addAll(dbsetMeals);
        return CommonResult.success(cachedSetMeals);
    }

    @Override
    public CommonResult<SetMeal> querySetMealById(Long id) {
        String setMealKey = RedisConstants.CACHE_SETMEAL_KEY + id;
        String setMealJson = stringRedisTemplate.opsForValue().get(setMealKey);
        log.info("套餐：{}", setMealJson);
        if (setMealJson != null) {
            return CommonResult.success(JSONUtil.toBean(setMealJson, SetMeal.class));
        }
        SetMeal setMeal = getById(id);
        if (setMeal == null) {
            return CommonResult.error(GlobalErrorCodeConstants.NOT_FOUND);
        }
        stringRedisTemplate.opsForValue().set(setMealKey, JSONUtil.toJsonStr(setMeal));
        return CommonResult.success(setMeal);
    }

    @Override
    public void updateSetMeal(SetMeal setMeal) {
        if (setMeal.getId() == null) {
            throw new ServiceException(400, "商品为空");
        }
        log.info("更新商品：{}", setMeal);
        updateById(setMeal);
        stringRedisTemplate.delete(RedisConstants.CACHE_SETMEAL_KEY + setMeal.getId());
    }

    @Override
    public void deleteSetMealById(Long id) {
        boolean remove = removeById(id);
        if (!remove) {
            throw new ServiceException(400, "删除商品失败");
        }
        stringRedisTemplate.delete(RedisConstants.CACHE_SETMEAL_KEY + id);
    }

    @Override
    public void deleteSetMealByIds(List<Long> ids) {
        CategoryService proxy = (CategoryService) AopContext.currentProxy();
        boolean removed = proxy.removeBatchByIds(ids);
        if (!removed) {
            throw new ServiceException(400, "删除商品失败");
        }
        ids.forEach(id -> stringRedisTemplate.delete(RedisConstants.CACHE_SETMEAL_KEY + id));
    }

    @Override
    public CommonResult<List<SetMeal>> listByCategoryId(Long categoryId) {
        List<SetMeal> setMealList = lambdaQuery()
                .eq(SetMeal::getCategoryId, categoryId)
                .list();
        return CommonResult.success(setMealList);
    }


}
